// imageProcessor.js
const fs = require('fs');
const path = require('path');
const Jimp = require('jimp');

/**
 * 添加水印
 * @example 
const ImageProcessor = require('./ImageProcessor');
const ip = new ImageProcessor({
    input: "./input",       // 输入文件夹
    output: "./output",     // 输出文件夹
    watermark: "0bian.com", // 文字水印
});

// 单个文件
ip.processImage('./input/image.png', './output/image1.png').then(e=>{
    console.log("单文件处理完成")
})

// 整个目录
ip.processDirectory('./input', './output').then(e=>{
    console.log("目录处理完成")
})
 */
class ImageProcessor {

  constructor(config) {
    this.inputDir = config.inputDir;
    this.outputDir = config.outputDir;
    this.watermark = config.watermark;
    this.overwrite = config.overwrite;
    this.setQuality(config.quality);
  }
  setQuality(quality){
    if(typeof quality != "number" || quality < 0 || 100 < quality) quality = 80;
    this.quality = quality;
  }

  /**
   * 
   * @param {String} inputPath 输入文件夹
   * @param {String} outputPath 输出文件夹
   * @param {String} watermark 水印文字内容
   * @param {Number} quality 默认80，压缩率 (0-100)
   */
  async processImage(inputPath, outputPath) {
    // 判断输入路径是否为文件
    if(!fs.existsSync(inputPath)) return "源路径不存在";
    if(!outputPath) return "输出路径不合法";

    if(!this.overwrite) {
      // 检测是否已经存在
      if(fs.existsSync(outputPath)) return "输出路径文件已存在";
    }

    const isFile = fs.lstatSync(inputPath).isFile();

    if (isFile) {
      // 处理单个文件
      try {
        let image = await Jimp.read(inputPath);
        if (!image) throw new Error('Failed to read the image.');

        // 正确加载字体（这里以预设字体为例）
        const font = await Jimp.loadFont(Jimp.FONT_SANS_32_WHITE);
        // 添加水印（这里以简单文字水印为例）
        let watermarkText = this.watermark;
        let watermarkMetrics = await Jimp.measureText(font, watermarkText);
        let x = Math.max(0, image.bitmap.width - watermarkMetrics - 10); // 确保水印不会超出右侧边界
        let y = Math.max(0, image.bitmap.height - 50); // 确保水印不会超出底部边界
        image.print(font, x, y, watermarkText);

        // 压缩图片
        image.quality(this.quality); // 调整输出质量

        // 保存图片到指定的输出路径
        await image.writeAsync(outputPath);

        // 检测图片是否成功写入
        if (fs.existsSync(outputPath) && fs.lstatSync(outputPath).isFile()) {
          console.log(`Successfully processed and saved as ${outputPath}`);
        } else {
          console.error(`Failed to write the processed image to ${outputPath}`);
        }
      } catch (error) {
        console.error(`Error processing image ${inputPath}:`, error);
      }
    } else {
      // 处理目录
      try {
        await this.processDirectory(inputPath, outputPath);
        console.log('All images have been processed');
      } catch (err) {
        console.error('An error occurred:', err);
      }
    }
  }

  async processDirectory(inputDir, outputDir) {
    if(!inputDir) inputDir = this.inputDir;
    if(!outputDir) outputDir = this.outputDir;

    const files = await new Promise((resolve, reject) =>
      fs.readdir(inputDir, (err, files) => {
        if (err) return reject(err);
        resolve(files);
      })
    );

    for (let file of files) {
      const filePath = path.join(inputDir, file);
      const stats = fs.statSync(filePath);

      if (stats.isDirectory()) {
        // 如果是目录，则递归调用
        const outputSubDir = path.join(outputDir, file);
        await fs.promises.mkdir(outputSubDir, { recursive: true });
        await this.processDirectory(filePath, outputSubDir);
      } else if (stats.isFile() && /\.(png|jpg|jpeg|gif)$/i.test(file)) {
        // 对于每个匹配的图片文件，调用 processImage 方法
        await this.processImage(filePath, path.join(outputDir, file));
      }
    }
  }
}

module.exports = ImageProcessor;